/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <gtest/gtest.h>
#include <fstream>
#include "plugin/plugin_manager_v2.h"
#include "plugin/codec_plugin.h"
#include "avcodec_codec_name.h"

using namespace std;
using namespace testing::ext;
using namespace OHOS::Media;
using namespace OHOS::Media::Plugins;

namespace OHOS {
namespace Media {
namespace Plugins {
constexpr uint32_t CHANNELS = 2;
constexpr uint32_t SAMPLE_RATE = 44100;
constexpr uint32_t UNSUPPORTED_CHANNELS_MIN = 0;
constexpr uint32_t UNSUPPORTED_CHANNELS_MAX = 256;
constexpr uint32_t UNSUPPORTED_MAX_INPUT_SIZE = 80 * 1024 * 1024 + 1;
constexpr uint32_t UNSUPPORTED_SAMPLE_RATE = 0;
constexpr int32_t MAX_INPUT_SIZE = 4096;
constexpr int32_t MIN_INPUT_SIZE = 16;
constexpr AudioSampleFormat SAMPLE_FORMAT = AudioSampleFormat::SAMPLE_S16LE;
constexpr AudioSampleFormat RAW_SAMPLE_FORMAT = AudioSampleFormat::SAMPLE_S16BE;
constexpr uint32_t SAMPLE_RATE_48000 = 48000;
const std::string OUTPUT_PREFIX = "/data/test/media/pcm_";
const std::string OUTPUT_SUFFIX = ".pcm";
constexpr int32_t BYTE_LENGTH_U8 = 1;
constexpr int32_t BYTE_LENGTH_S16 = 2;
constexpr int32_t BYTE_LENGTH_S24 = 3;
constexpr int32_t BYTE_LENGTH_S32_F32 = 4;
constexpr int32_t BYTE_LENGTH_DOUBLE = 8;
constexpr int32_t AUDIO_BITS_16 = 16;
constexpr int32_t AUDIO_BITS_20 = 20;
constexpr int32_t AUDIO_BITS_24 = 24;
// {sampleFormat, {filePath, outputName}}
const std::unordered_map<AudioSampleFormat, std::pair<std::string, std::string>> inputFormatPathMap = {
    {AudioSampleFormat::SAMPLE_S8, std::make_pair("/data/test/media/pcm_s8.pcm", "s8_")},
    {AudioSampleFormat::SAMPLE_F64LE, std::make_pair("/data/test/media/pcm_f64le.pcm", "f64le_")},
    {AudioSampleFormat::SAMPLE_S64LE, std::make_pair("/data/test/media/pcm_s64le.pcm", "s64le_")},
    {AudioSampleFormat::SAMPLE_S8P, std::make_pair("/data/test/media/pcm_s8_planar.pcm", "s8p_")},
    {AudioSampleFormat::SAMPLE_S16LEP, std::make_pair("/data/test/media/pcm_s16le_planar.pcm", "s16lep_")},
    {AudioSampleFormat::SAMPLE_S16BEP, std::make_pair("/data/test/media/pcm_s16be_planar.pcm", "s16bep_")},
    {AudioSampleFormat::SAMPLE_S24LEP, std::make_pair("/data/test/media/pcm_s24le_planar.pcm", "s24lep_")},
    {AudioSampleFormat::SAMPLE_S32LEP, std::make_pair("/data/test/media/pcm_s32le_planar.pcm", "s32lep_")},
    {AudioSampleFormat::SAMPLE_DVD, std::make_pair("/data/test/media/pcm_bluray_16bit.pcm", "dvd_16bit_")},
    {AudioSampleFormat::SAMPLE_BLURAY, std::make_pair("/data/test/media/pcm_bluray_24bit.pcm", "bluray_24bit_")},
};
// {sampleFormat, outputName}
const std::vector<pair<AudioSampleFormat, std::string>> outputFormats = {
    std::make_pair(AudioSampleFormat::SAMPLE_U8, "to_u8"),
    std::make_pair(AudioSampleFormat::SAMPLE_S16LE, "to_s16le"),
    std::make_pair(AudioSampleFormat::SAMPLE_S24LE, "to_s24le"),
    std::make_pair(AudioSampleFormat::SAMPLE_S32LE, "to_s32le"),
    std::make_pair(AudioSampleFormat::SAMPLE_F32LE, "to_f32le")
};

class RawDecoderUnitTest : public testing::Test, public DataCallback {
public:
    static void SetUpTestCase(void);
    static void TearDownTestCase(void);
    void SetUp() override;
    void TearDown() override;

    void OnInputBufferDone(const shared_ptr<Media::AVBuffer> &inputBuffer) override
    {
        (void)inputBuffer;
        std::shared_ptr<Meta> para = std::make_shared<Meta>();
        // for mutex test
        decoder_->GetParameter(para);
    }

    void OnOutputBufferDone(const shared_ptr<Media::AVBuffer> &outputBuffer) override
    {
        (void)outputBuffer;
        std::shared_ptr<Meta> para = std::make_shared<Meta>();
        // for mutex test
        decoder_->GetParameter(para);
    }

    void OnEvent(const shared_ptr<Plugins::PluginEvent> event) override
    {
        (void)event;
    }

    int32_t GetFormatBytes(AudioSampleFormat format)
    {
        int32_t bytesSize = BYTE_LENGTH_S16;
        switch (format) {
            case AudioSampleFormat::SAMPLE_S16BE:
            /* fall-through */
            case AudioSampleFormat::SAMPLE_S16LE:
                bytesSize = BYTE_LENGTH_S16;
                break;
            case AudioSampleFormat::SAMPLE_S24BE:
            /* fall-through */
            case AudioSampleFormat::SAMPLE_S24LE:
            case AudioSampleFormat::SAMPLE_S24LEP:
                bytesSize = BYTE_LENGTH_S24;
                break;
            case AudioSampleFormat::SAMPLE_S32BE:
            /* fall-through */
            case AudioSampleFormat::SAMPLE_S32LE:
            case AudioSampleFormat::SAMPLE_S32LEP:
            case AudioSampleFormat::SAMPLE_F32BE:
            /* fall-through */
            case AudioSampleFormat::SAMPLE_F32LE:
                bytesSize = BYTE_LENGTH_S32_F32;
                break;
            case AudioSampleFormat::SAMPLE_F64LE:
            case AudioSampleFormat::SAMPLE_S64LE:
            case AudioSampleFormat::SAMPLE_F64BE:
                bytesSize = BYTE_LENGTH_DOUBLE;
                break;
            case AudioSampleFormat::SAMPLE_S8:
            case AudioSampleFormat::SAMPLE_S8P:
            case AudioSampleFormat::SAMPLE_U8:
                bytesSize = BYTE_LENGTH_U8;
                break;
            case AudioSampleFormat::SAMPLE_DVD: {
                int32_t audioBits = AUDIO_BITS_16;
                if (meta_->Get<Tag::AUDIO_BITS_PER_RAW_SAMPLE>(audioBits)) {
                    bytesSize = audioBits == AUDIO_BITS_20 ? BYTE_LENGTH_S24 : BYTE_LENGTH_S16;
                }
                break;
            }
            case AudioSampleFormat::SAMPLE_BLURAY: {
                int32_t audioBits = AUDIO_BITS_24;
                bytesSize = BYTE_LENGTH_S24;
                if (meta_->Get<Tag::AUDIO_BITS_PER_RAW_SAMPLE>(audioBits)) {
                    bytesSize = audioBits == AUDIO_BITS_16 ? BYTE_LENGTH_S16 : BYTE_LENGTH_S24;
                }
                break;
            }
            default:
                break;
        }
        return bytesSize;
    }

    void SetupParameter(AudioSampleFormat inputFormat, AudioSampleFormat outputFormat)
    {
        meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
        meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE_48000);
        meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(inputFormat);
        if (inputFormat == AudioSampleFormat::SAMPLE_DVD) {
            meta_->Set<Tag::AUDIO_BITS_PER_RAW_SAMPLE>(AUDIO_BITS_16);
        } else if (inputFormat == AudioSampleFormat::SAMPLE_BLURAY) {
            meta_->Set<Tag::AUDIO_BITS_PER_RAW_SAMPLE>(AUDIO_BITS_24);
        }
        meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(outputFormat);
    }

protected:
    shared_ptr<Media::Meta> meta_ = nullptr;
    shared_ptr<CodecPlugin> decoder_ = nullptr;
};

void RawDecoderUnitTest::SetUpTestCase(void)
{
    cout << "[SetUpTestCase]: " << endl;
}

void RawDecoderUnitTest::TearDownTestCase(void)
{
    cout << "[TearDownTestCase]: " << endl;
}

void RawDecoderUnitTest::SetUp(void)
{
    auto plugin = PluginManagerV2::Instance().CreatePluginByName("OH.Media.Codec.Decoder.Audio.Raw");
    if (plugin == nullptr) {
        cout << "not support raw" << endl;
        return;
    }
    decoder_ = reinterpret_pointer_cast<CodecPlugin>(plugin);
    decoder_->SetDataCallback(this);
    meta_ = make_shared<Media::Meta>();
}

void RawDecoderUnitTest::TearDown(void)
{
    if (decoder_ != nullptr) {
        decoder_ = nullptr;
    }
}

HWTEST_F(RawDecoderUnitTest, InputBuffer_Nullptr_001, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    decoder_->SetParameter(meta_);
    EXPECT_EQ(Status::OK, decoder_->Init());
    EXPECT_EQ(Status::OK, decoder_->Prepare());
    EXPECT_EQ(Status::OK, decoder_->Start());
    EXPECT_EQ(Status::OK, decoder_->Stop()); // set inputBuffer_ nullptr
    EXPECT_EQ(Status::OK, decoder_->Stop());
    EXPECT_EQ(Status::OK, decoder_->Flush());
    EXPECT_EQ(Status::OK, decoder_->Reset());
    EXPECT_EQ(Status::OK, decoder_->Release());
}

HWTEST_F(RawDecoderUnitTest, GetMetaData_001, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE); // no AUDIO_CHANNEL_COUNT
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, GetMetaData_002, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS); // no AUDIO_SAMPLE_RATE
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, GetMetaData_003, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE); // no AUDIO_SAMPLE_FORMAT
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, GetMetaData_004, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT); // no AUDIO_RAW_SAMPLE_FORMAT
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, CheckFormat_001, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(UNSUPPORTED_CHANNELS_MIN); // check channels fail
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, CheckFormat_002, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(UNSUPPORTED_SAMPLE_RATE); // check sampleRate fail
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, CheckFormat_003, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(INVALID_WIDTH); // check sampleFormat fail
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, CheckFormat_004, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(INVALID_WIDTH); // check sampleFormat fail
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, CheckFormat_005, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(UNSUPPORTED_CHANNELS_MAX); // check channels fail
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, SetParameter_001, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_MAX_INPUT_SIZE>(MAX_INPUT_SIZE);
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, SetParameter_002, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_MAX_INPUT_SIZE>(MIN_INPUT_SIZE);
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, SetParameter_003, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_MAX_INPUT_SIZE>(UNSUPPORTED_MAX_INPUT_SIZE);
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
}

HWTEST_F(RawDecoderUnitTest, GetFormatBytes_001, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(SAMPLE_FORMAT);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(RAW_SAMPLE_FORMAT);
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
    EXPECT_EQ(Status::OK, decoder_->Start());
    std::shared_ptr<Meta> config = std::make_shared<Meta>();
    EXPECT_EQ(Status::OK, decoder_->GetParameter(config));
}

HWTEST_F(RawDecoderUnitTest, GetFormatBytes_002, TestSize.Level1)
{
    EXPECT_NE(Status::OK, decoder_->SetParameter(meta_));
    EXPECT_EQ(Status::OK, decoder_->Start());
    std::shared_ptr<Meta> config = std::make_shared<Meta>();
    EXPECT_EQ(Status::OK, decoder_->GetParameter(config));
}

HWTEST_F(RawDecoderUnitTest, QueueInputBuffer_001, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F32LE);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F64BE); // SAMPLE_F64BE
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
    int32_t oneFrameSize = 64000; // capacity
    auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
    shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    inputBuffer->memory_->SetSize(64000); // size % bytesSize == 0 && size > maxInputSize_
    EXPECT_EQ(Status::OK, decoder_->QueueInputBuffer(inputBuffer));
    shared_ptr<AVBuffer> outputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    EXPECT_NE(Status::OK, decoder_->QueueOutputBuffer(outputBuffer));
}

HWTEST_F(RawDecoderUnitTest, QueueInputBuffer_002, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F32LE);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F64BE); // SAMPLE_F64BE
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
    int32_t oneFrameSize = 9; // capacity
    auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
    shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    inputBuffer->memory_->SetSize(9); // size % bytesSize != 0
    EXPECT_EQ(Status::ERROR_UNKNOWN, decoder_->QueueInputBuffer(inputBuffer));
}

HWTEST_F(RawDecoderUnitTest, QueueInputBuffer_003, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F32LE);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F32BE); // not SAMPLE_F64BE
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
    int32_t oneFrameSize = 16000; // capacity
    auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
    shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    inputBuffer->memory_->SetSize(16000); // size % bytesSize == 0
    EXPECT_EQ(Status::OK, decoder_->QueueInputBuffer(inputBuffer));
    shared_ptr<AVBuffer> outputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    EXPECT_NE(Status::OK, decoder_->QueueOutputBuffer(outputBuffer));
}

HWTEST_F(RawDecoderUnitTest, QueueInputBuffer_004, TestSize.Level1)
{
    meta_->Set<Tag::AUDIO_CHANNEL_COUNT>(CHANNELS);
    meta_->Set<Tag::AUDIO_SAMPLE_RATE>(SAMPLE_RATE);
    meta_->Set<Tag::AUDIO_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F32LE);
    meta_->Set<Tag::AUDIO_RAW_SAMPLE_FORMAT>(AudioSampleFormat::SAMPLE_F32BE); // not SAMPLE_F64BE
    EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));
    int32_t oneFrameSize = 16; // capacity
    auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
    shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    inputBuffer->memory_->SetSize(16); // size % bytesSize == 0 && size < maxInputSize_
    EXPECT_EQ(Status::OK, decoder_->QueueInputBuffer(inputBuffer));
    shared_ptr<AVBuffer> outputBuffer = AVBuffer::CreateAVBuffer(avAllocator, oneFrameSize);
    EXPECT_EQ(Status::OK, decoder_->QueueOutputBuffer(outputBuffer));
}

HWTEST_F(RawDecoderUnitTest, QueueInputBuffer_005, TestSize.Level1)
{
    for (auto &elem : inputFormatPathMap) {
        AudioSampleFormat inputFormat = elem.first;
        auto pair = elem.second;
        std::string inputFilePath = pair.first;
        std::string srcOutName = pair.second;

        for (auto outElem : outputFormats) {
            AudioSampleFormat outputFormat = outElem.first;
            std::string destName = outElem.second;
            SetupParameter(inputFormat, outputFormat);
            EXPECT_EQ(Status::OK, decoder_->SetParameter(meta_));

            std::ifstream inputFile;
            inputFile.open(inputFilePath, std::ios::binary | std::ios::ate);
            int32_t fileSize = static_cast<int32_t>(inputFile.tellg());
            inputFile.seekg(0, std::ios::beg);

            auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
            shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, fileSize);
            inputBuffer->memory_->SetSize(fileSize);
            inputFile.read(reinterpret_cast<char*>(inputBuffer->memory_->GetAddr()), fileSize);
            EXPECT_EQ(Status::OK, decoder_->QueueInputBuffer(inputBuffer));

            std::ofstream outputFile;
            std::string outputPath = OUTPUT_PREFIX + srcOutName + destName + OUTPUT_SUFFIX;
            outputFile.open(outputPath, std::ios::out | std::ios::binary);

            int32_t srcBytesSize = GetFormatBytes(inputFormat);
            int32_t destBytesSize = GetFormatBytes(outputFormat);
            int32_t totalSamples = fileSize / (CHANNELS * srcBytesSize);
            int32_t outputSize = totalSamples * CHANNELS * destBytesSize;
            shared_ptr<AVBuffer> outputBuffer = AVBuffer::CreateAVBuffer(avAllocator, outputSize);
            shared_ptr<AVBuffer> emptyOutputBuffer = AVBuffer::CreateAVBuffer(avAllocator, outputSize);

            Status ret = Status::ERROR_AGAIN;
            int32_t pos = 0;
            while (ret == Status::ERROR_AGAIN) {
                ret = decoder_->QueueOutputBuffer(emptyOutputBuffer);
                outputBuffer->memory_->Write(emptyOutputBuffer->memory_->GetAddr(),
                                            emptyOutputBuffer->memory_->GetSize(), pos);
                pos += emptyOutputBuffer->memory_->GetSize();
            }
            EXPECT_EQ(Status::OK, ret);
            EXPECT_EQ(outputSize, outputBuffer->memory_->GetSize());
            outputFile.write(reinterpret_cast<char*>(outputBuffer->memory_->GetAddr()),
                    outputBuffer->memory_->GetSize());

            inputFile.close();
            outputFile.close();
        }
    }
}
} // namespace Plugins
}
}